#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__author__ = 'heibbai@gmail.com'

from google.appengine.api import users
from google.appengine.api import urlfetch
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import login_required
from google.appengine.ext.webapp.util import run_wsgi_app
from model import *
import gdata.photos.service
import gdata.alt.appengine
import gdata.auth
import settings
import os

class BaseHandler(webapp.RequestHandler):
    def __init__(self):
        webapp.RequestHandler.__init__(self)
        self.user_email = ""
        self.session_token = ""
        self.client = None
    def render_out(self,template_values,file):
        file = 'template/default/'+ file
        path = os.path.join(os.path.dirname(__file__),file)
        self.response.out.write(template.render(path, template_values))
    def error(self,error_code,error_msg=None):
        if error_msg == None: error_msg = str(error_code)
        if error_code == 404:
            template_file= 'error-404.html'
        else:
            template_file = 'error.html'
        template_values = {
                'error_code' : error_code,
                'error_msg' : error_msg }
        self.render_out(template_values,template_file)

class Error404(BaseHandler):
    def get(self):
        self.error(404)
def check_auth(handler):
    def wrapper(self,*args,**kwargs):
        user = users.get_current_user()
        session_token = None
        single_use_token = gdata.auth.extract_auth_sub_token_from_url(self.request.uri)
        #redirect from google's auth page 
        if single_use_token: 
            try:
                session_token = UpgradeAndStoreToken(user.email(),single_use_token)
            except TokenError :
                self.error(403,'Upgrader to session token failed')
        # session_token null,look up from token store
        if session_token is None:
            session_token = LookupToken(user.email())
        # still null, redirect to auth page
        if session_token is None:
            self.redirect('/auth')
        # first auth, th64en just redirect to ablum page
        elif single_use_token and session_token:
            self.redirect('/albums')
        # auth checked, set user_email and session_token
        else:
            self.user_email = user.email()
            self.client = gdata.photos.service.PhotosService()
            gdata.alt.appengine.run_on_appengine(self.client)
            self.client.SetAuthSubToken(session_token)
            try:
                handler(self,*args,**kwargs) #todo this may raise some excption,take care of it
            except gdata.photos.service.GooglePhotosException,request_error:
                error_code = request_error[0]
                error_msg = request_error[2]
                if error_code == 403: #token invide, need to be deleted
                    DeleteInvalidToken(user.email())
                self.error(error_code,error_msg)
    return wrapper

class ShowAlbums(BaseHandler):
    @login_required
    @check_auth
    def get(self):
        user = users.get_current_user()
        albums_feed = self.client.GetFeed('/data/feed/api/user/default')
        albums = [ {'title':album.title.text, 'id':album.gphoto_id.text, 
            'count':album.numphotos.text, 'thumbnail_url':album.media.thumbnail[0].url}
            for album in albums_feed.entry]
        template_values ={
                'user' : user.email(),
                'albums' : albums,
                'sign_url' : users.create_logout_url('/'),
                }
        self.render_out(template_values,'albums.html')

class ShowPhotos(BaseHandler):
    @login_required
    @check_auth
    def get(self):
        album_id = self.request.get('id')
        if album_id == '':
            self.redirect('/albums')
        else:
            index = self.request.get('page')
            if index == '': index = 1
            else: index = int(index)
            albums_feed = self.client.GetFeed('/data/feed/api/user/default')
            total_number = ([ int(album.numphotos.text) for album in albums_feed.entry
                    if album.gphoto_id.text == album_id])[0]
            pagination = False
            pages = []
            if total_number > 100: 
                pagination = True
                n_page = (total_number/100 + ( total_number%100 and 1 or 0))
                if index > n_page: index = 1
                pages = (range(1 + n_page))[1:]

            photos = self.client.GetFeed(
                    ('/data/feed/api/user/default/albumid/%s?kind=photo' %album_id),
                    limit = 99, start_index=(index-1)*99+1 )
            template_values = {
                    'user': users.get_current_user(),
                    'sign_url' : users.create_logout_url('/'),
                    'album_id' : album_id,
                    'photos' : photos.entry,
                    'pagination': pagination,
                    'pages': pages,
                    'page' : index,
                    }
            self.render_out(template_values,'photos.html')

class AuthPage(BaseHandler):
    @login_required
    def get(self):
        revoke = self.request.get('revoke')
        revoke_msg = None
        user = users.get_current_user()
        if revoke == 'true':
            try:
                RevokeToken(user.email())
            except:
                revoke_msg = "Revoke failed."
            else:
                revoke_msg = "Revoke done."
        auth_state = IsAuthed(user.email())
        next = "http://%s/albums" %settings.HOST_NAME
        scope = 'http://picasaweb.google.com/data/'
        client = gdata.service.GDataService()
        auth_url = users.create_login_url(client.GenerateAuthSubURL(next,scope,secure=False,session=True))
        #auth_url = client.GenerateAuthSubURL(next,scope,secure=False,session=True)
        template_values = {
                'user' : user.email(),
                'sign_url' : users.create_logout_url('/'),
                'sign_text' : 'Sign Out',
                'auth_state' : auth_state,
                'auth_url' : auth_url,
                'revoke_msg' : revoke_msg,
                }
        self.render_out(template_values,'auth.html')

class MainPage(BaseHandler):
    def get(self):
        user = users.get_current_user() 
        if user: user = user.email()
        url = None
        url_text = None
        if user:
            sign_url=users.create_logout_url('/')
            sign_text='Sign Out'
        else:
            sign_url=users.create_login_url('/albums')
            sign_text='Sign In'
        template_values = {
                'user' : user,
                'sign_url' : sign_url,
                'sign_text': sign_text,}
        self.render_out(template_values,'index.html')

class AboutPage(BaseHandler):
    def get(self):
        user = users.get_current_user() 
        if user: user = user.email()
        url = None
        url_text = None
        if user:
            sign_url=users.create_logout_url('/')
            sign_text='Sign Out'
        else:
            sign_url=users.create_login_url('/about')
            sign_text='Sing In'
        template_values = {
                'user' : user,
                'sign_url' : sign_url,
                'sign_text': sign_text,}
        self.render_out(template_values,'about.html')




application = webapp.WSGIApplication([
            ('/',MainPage),
            ('/about',AboutPage),
            ('/albums',ShowAlbums),
            ('/album',ShowPhotos),
            ('/auth',AuthPage),
            ('.*',Error404),],debug=True)

def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()
